import numpy as np
from generation_data import GenerationData
from utils import Utils

class Algorithm:
    """
    算法类，负责数据分析和处理算法
    
    主要功能：
    - 分析数字连续不出现的次数
    - 计算投入和回报
    - 生成各种矩阵用于分析
    """
    
    @staticmethod
    def continuous_data(record_matrix, input_ratio=6, output_ratio=10):
        """ 
        分析record_matrix中连续出现的次数，生成多种矩阵用于后续分析
        
        参数：
            record_matrix (numpy.ndarray): 记录矩阵，标记每个数字是否出现
            input_ratio (int): 投入倍率起始值，当连续未出现次数≥此值时开始投入
            output_ratio (int): 退出倍率，当连续未出现次数>此值时停止投入
            
        返回：
            tuple: 包含五个numpy数组:
                - continuous_matrix: 连续未出现的记录矩阵
                - input_matrix: 投入记录矩阵(投入次数)
                - hit_matrix: 中奖记录矩阵
                - input_m_matrix: 投入金额矩阵
                - hit_m_matrix: 中奖金额矩阵
        """
        continuous_matrix = np.zeros((record_matrix.shape[0], 80), dtype=int)  # 连续未出现的记录 
        input_matrix = np.zeros((record_matrix.shape[0], 80), dtype=int)  # input 跟进记录 投倍情况
        input_m_matrix = np.zeros((record_matrix.shape[0], 80), dtype=int)  # input m 
        hit_matrix = np.zeros((record_matrix.shape[0], 80), dtype=int)  # hit 记录 投中倍数
        hit_m_matrix = np.zeros((record_matrix.shape[0], 80), dtype=int)  # hit m

        continuous_matrix[0] = 1 - record_matrix[0]  # 第一行为1的设置为0，为0的设置为1
        for i in range(1, record_matrix.shape[0]):  # 从第二行开始 1~99
            for j in range(80):
                # 记录连续
                if record_matrix[i, j] == 0:
                    continuous_matrix[i, j] = continuous_matrix[i-1, j] + 1
                else:
                    continuous_matrix[i, j] = 0
                # 计算本次投入
                # 上一次 大于等于input_ratio就投入，小于output_ratio就不投入
                if continuous_matrix[i-1, j] >= input_ratio and continuous_matrix[i-1, j] < output_ratio:  
                    # 持续投入的情况，当前一定是未hit
                    input_matrix[i, j] = input_matrix[i-1, j] + 1
                else:
                    # 当前高于最大，不再投入了 一定不中的
                    input_matrix[i, j] = 0
                
                # 计算本次中奖， 
                # 有投入才看是否中
                # record_matrix 记录 =1 中
                if input_matrix[i, j] > 0 and record_matrix[i, j] == 1:
                    hit_matrix[i, j] = input_matrix[i, j]

        # 计算投入金额和回报金额
        input_m_matrix = np.where(input_matrix != 0, 2 ** input_matrix, 0)  # input_matrix 中非0的值取平方
        hit_m_matrix = np.where(hit_matrix != 0, (2 ** hit_matrix) / 2 * 4.6, 0)  # hit_matrix 中非0的值取平方，回报率计算

        return continuous_matrix, input_matrix, hit_matrix, input_m_matrix, hit_m_matrix

    @staticmethod
    def generate_input_output_data(record_row=100, input_ratio=6, output_ratio=100, local=False):
        """ 
        生成输入输出数据，并保存各种矩阵到CSV文件
        
        参数：
            record_row (int): 多少期号码
            input_ratio (int): 跟入倍率
            output_ratio (int): 退出倍率
            local (bool): 是否使用output.csv历史数据文件
            
        返回：
            numpy.ndarray: 最终生成的结果数据，7列表示不同的指标
        """
        generate_data = np.zeros((record_row, 7), dtype=float)
        
        # 将 generate_data 第一列全部设置为 record_row 的值
        generate_data[:, 1] = record_row
        # 将 generate_data 第二列全部设置为 input_ratio 的值
        generate_data[:, 2] = input_ratio
        # 将 generate_data 第三列全部设置为 output_ratio 的值
        generate_data[:, 3] = output_ratio
        
        # 生成基础数据
        data_matrix_all, data_matrix, record_matrix = GenerationData.generate_simulation_data(record_row, local)
        continuous_matrix, input_matrix, hit_matrix, input_m_matrix, hit_m_matrix = Algorithm.continuous_data(
            record_matrix, input_ratio, output_ratio
        )

        # 加入记录一下 日期
        generate_data[:, 0] = data_matrix_all[:, 0]
        # 第4列赋值 input_m_matrix (投入总额)
        generate_data[:, 4] = np.round(input_m_matrix.sum(axis=1), 2)
        # 第5列赋值 hit_m_matrix (回报总额)
        generate_data[:, 5] = np.round(hit_m_matrix.sum(axis=1), 2)
        # 第6列是盈亏，等于回报减去投入
        generate_data[:, 6] = np.round(generate_data[:, 5] - generate_data[:, 4], 2)
        
        # 保存各种矩阵到CSV文件
        Utils.save_to_csv(data_matrix_all, 'data/data_matrix_all.csv')
        Utils.save_to_csv(data_matrix, 'data/data_matrix.csv')
        Utils.save_to_csv(record_matrix, 'data/record_matrix.csv')
        Utils.save_to_csv(continuous_matrix, 'data/continuous_matrix.csv')
        Utils.save_to_csv(input_matrix, 'data/input_matrix.csv')
        Utils.save_to_csv(hit_matrix, 'data/hit_matrix.csv')
        Utils.save_to_csv(input_m_matrix, 'data/input_m_matrix.csv')
        Utils.save_to_csv(hit_m_matrix, 'data/hit_m_matrix.csv')
        
        return generate_data